package network.server;

import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;

import network.Client;

/**
 * Client list is a data class which is used for server to store the current
 * users who are connected to the server.
 * 
 * @author Jie Zhao(288654)
 * 
 */
public class ClientList extends Observable {
	private static ClientList instance = null;
	private int i = 1;

	private ClientList() {
	}

	/**
	 * 
	 * @return an instance of clientlist
	 */
	public static ClientList getInstance() {
		if (instance == null) {
			instance = new ClientList();
		}
		return instance;
	}

	private List<Client> clientList = Collections
			.synchronizedList(new ArrayList<Client>());

	/**
	 * clear the client list
	 */
	public synchronized void clear() {
		clientList.clear();
		setChanged();
		notifyObservers();
	}

	/**
	 * add a client to the list
	 * 
	 * @param client
	 */
	public synchronized void addClient(Client client) {

		Client c = searchClient(client.getName());
		if (c != null) {
			client.setName(client.getName() + ":" + i++);
		}

		clientList.add(client);
		setChanged();
		notifyObservers();
	}

	/**
	 * notify the observes
	 */
	public void update() {
		setChanged();
		notifyObservers();
	}

	/**
	 * check if a client is in the list or not
	 * 
	 * @param s
	 * @return
	 */
	public synchronized boolean isInList(Socket s) {
		if (s == null)
			return false;
		for (Client c : clientList) {
			if (s.equals(c.getClientSocket())) {
				return true;
			}

		}
		return false;
	}

	/**
	 * remove a client from the list
	 * 
	 * @param client
	 */
	public synchronized void removeClient(Client client) {
		clientList.remove(client);
		setChanged();
		notifyObservers();
	}

	/**
	 * remove a client specified by the socket from the list
	 * 
	 * @param s
	 */
	public synchronized void removeClient(Socket s) {
		for (Client c : clientList) {
			if (c.getClientSocket().equals(s)) {
				clientList.remove(c);
			}
		}

	}

	/**
	 * remove a client specified by the username
	 * 
	 * @param username
	 */
	public synchronized void removeClient(String username) {
		Client c = searchClient(username);
		if (c != null)
			removeClient(c);
	}

	/**
	 * search a client in the list
	 * 
	 * @param clientName
	 * @return
	 */
	public synchronized Client searchClient(String clientName) {
		for (Client c : clientList) {
			if (c.getName().equals(clientName)) {
				return c;
			}
		}
		return null;
	}

	/**
	 * add a client to the list
	 * 
	 * @param name
	 */
	public synchronized void addClient(String name) {
		Client c = new Client();
		c.setName(name);
		addClient(c);
	}

	/**
	 * get the list of clients
	 * 
	 * @return
	 */
	public synchronized List<Client> getClientList() {
		return clientList;
	}
}
